package org.lhq.filter;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.SneakyThrows;
import org.lhq.entity.dto.PayloadDto;
import org.lhq.serivce.AuthService;
import org.lhq.utils.TokenUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;


/**
 * @author Wallace
 */

@Component
@RefreshScope
public class AuthFilter implements GlobalFilter, Ordered {

  private static final Logger LOGGER = LoggerFactory.getLogger(AuthFilter.class);



  @Value("${auth.skip.urls}")
  private String[] skipAuthUrls;

  /*@Value("${jwt.blacklist.key.format}")
  private String jwtBlacklistKeyFormat;*/
  @Resource
  private AuthService authService;


  @Override
  public int getOrder() {
    return -100;
  }

  @SneakyThrows
  @Override
  public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    String url = exchange.getRequest().getURI().getPath();

    LOGGER.info("请求路URL为:{}", url);
    // 不需要验证的路径，跳过
    if (true) {
      return chain.filter(exchange);
    }
    // 从请求头中取出token
    String token = exchange.getRequest().getHeaders().getFirst("Authorization");
    // 未携带token或token在黑名单内
  /*  if (StrUtil.isBlank(token)) {
      ServerHttpResponse originalResponse = exchange.getResponse();
      originalResponse.setStatusCode(HttpStatus.OK);
      originalResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
      byte[] response =
          "{\"code\": \"401\",\"msg\": \"401 未认证.\"}".getBytes(StandardCharsets.UTF_8);
      DataBuffer buffer = originalResponse.bufferFactory().wrap(response);
      return originalResponse.writeWith(Flux.just(buffer));
    }*/
    token = Arrays.stream(StrUtil.split(token," "))
            .filter(str -> !StrUtil.equals(str,TokenUtil.TOKEN_PREFIX_WITHOUT_SPACE))
            .findAny()
            .orElse("");
    try {
      PayloadDto payloadDto = TokenUtil.verifyTokenByHMAC(token);
      LOGGER.info("token剩余有效时间:{} 分钟",TimeUnit.MINUTES.convert(payloadDto.getExp()- DateUtil.current(),TimeUnit.MILLISECONDS));
      if (payloadDto.getExp()- DateUtil.current() <= TimeUnit.MILLISECONDS.convert(10,TimeUnit.MINUTES)){
        LOGGER.info("自动刷新token开始");
        Long userId = payloadDto.getUserId();
        String username = payloadDto.getUsername();
        List<String> authorities = payloadDto.getAuthorities();
        PayloadDto payLoadDto = TokenUtil.getPayLoadDto(userId, username, authorities);
        String newToken = TokenUtil.generateTokenByHMAC(JSONUtil.toJsonStr(payLoadDto));
        HttpHeaders headers = exchange.getResponse().getHeaders();
        headers.add(TokenUtil.AUTH_HEADER_KEY,TokenUtil.TOKEN_PREFIX+newToken);
        headers.add("Access-Control-Expose-Headers",TokenUtil.AUTH_HEADER_KEY);
      }
      // 将现在的request，添加当前身份
      ServerHttpRequest mutableReq =
              exchange.getRequest().mutate()
                      .header("Authorization-UserName", payloadDto.getUsername())
                      .header("Authorization-UserId",StrUtil.toString(payloadDto.getUserId()))
                      .build();
      ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build();
      return chain.filter(mutableExchange);
    }catch (Exception e){
      LOGGER.error("token错误",e);
      ServerHttpResponse response = exchange.getResponse();
      response.setStatusCode(HttpStatus.UNAUTHORIZED);
      response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
      byte[] data = "非法token".getBytes(StandardCharsets.UTF_8);
      DataBuffer buffer = response.bufferFactory().wrap(data);
      return response.writeWith(Flux.just(buffer));
    }




  }


}

